package com.lcj.dr.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lcj.common.util.MicroAppUtil;
import com.lcj.common.util.Result;
import com.lcj.dr.controller.form.SearchDriverByPageForm;
import com.lcj.dr.controller.form.UpdateDriverHomeForm;
import com.lcj.dr.controller.form.UpdatePhoneForm;
import com.lcj.dr.db.dao.*;
import com.lcj.dr.db.pojo.DriverFineEntity;
import com.lcj.dr.db.pojo.DriverLockdownEntity;
import com.lcj.dr.db.pojo.DriverSettingsEntity;
import com.lcj.dr.db.pojo.WalletEntity;
import com.lcj.dr.service.DriverService;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.iai.v20200303.IaiClient;
import com.tencentcloudapi.iai.v20200303.models.CreatePersonRequest;
import com.tencentcloudapi.iai.v20200303.models.CreatePersonResponse;
import com.tencentcloudapi.iai.v20200303.models.VerifyPersonRequest;
import com.tencentcloudapi.iai.v20200303.models.VerifyPersonResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author  : lcj
 * @create 2022/11/2 13:48
 */

@Service
@Slf4j
public class DriverServiceImpl implements DriverService {

    @Value("${tencent.cloud.secretId}")
    private String secretId;

    @Value("${tencent.cloud.secretKey}")
    private String secretKey;

    @Value("${tencent.cloud.face.groupName}")
    private String groupName;

    @Value("${tencent.cloud.face.region}")
    private String region;

    /**
     * 里面包含将临时授权转换为openId字符串的方法
     */
    @Resource
    private MicroAppUtil microAppUtil;

    @Resource
    private DriverDao driverDao;

    @Resource
    private DriverSettingsDao settingsDao;

    @Resource
    private WalletDao walletDao;

    @Resource
    private DriverRecognitionDao recognitionDao;

    @Resource
    private DriverLockdownDao driverLockdownDao;

    @Resource
    private DriverFineDao driverFineDao;


    /**
     * 查询司机openId
     * @param driverId
     * @return openId
     */
    @Override
    public String searchDriverOpenId(long driverId) {
        String openId = driverDao.searchDriverOpenId(driverId);
        return openId;
    }

    /**
     * 注册新司机
     * @param param
     * @return Result
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @LcnTransaction
    public Result registerNewDriver(Map param) {
        //获取临时授权字符串
        String code = MapUtil.getStr(param, "code");
        //请求微信API将临时授权兑换成永久授权
        String openId = microAppUtil.getOpenId(code);

        HashMap tempParam = new HashMap<>() {{
            put("openId", openId);
        }};
        //查看是否存在当前openId对应的记录
        if (driverDao.hasDriver(tempParam)!=0) {
            String driverId = driverDao.searchDriverId(openId);
            return Result.ok("该微信已注册过!").put("userId", driverId);
            //throw new AochException("该微信已注册过，请登录");
        }
        //如果不存在当前openId对应的记录
        param.put("openId",openId);
        //插入司机记录
        driverDao.registerNewDriver(param);
        //查询司机主键值
        String driverId = driverDao.searchDriverId(openId);

        //1) 添加司机设置记录
        DriverSettingsEntity settingsEntity = new DriverSettingsEntity();
        settingsEntity.setDriverId(Long.parseLong(driverId));
        JSONObject json = new JSONObject();
        //定向接单
        json.put("orientation", "");
        //自动听单
        json.put("listenService", true);
        //代驾订单预估里程不限，司机不挑订单
        json.put("orderDistance", 0);
        //接收距离司机5公里以内的代驾单
        json.put("rangeDistance", 5);
        //自动抢单
        json.put("autoAccept", false);
        settingsEntity.setSettings(json.toString());
        settingsDao.insertDriverSettings(settingsEntity);

        //2) 添加司机钱包记录
        WalletEntity walletEntity = new WalletEntity();
        walletEntity.setDriverId(Long.parseLong(driverId));
        walletEntity.setBalance(new BigDecimal("0"));
        //支付密码为空，用户支付的时候，系统会自动提示用户设置支付密码
        walletEntity.setPassword(null);
        walletDao.insert(walletEntity);

        //Bff层需要根据司机id颁发token令牌
        return Result.ok("注册成功!").put("userId", driverId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LcnTransaction
    public int updateDriverAuth(Map param) {
        int rows = driverDao.updateDriverAuth(param);
        return rows;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LcnTransaction
    public String createDriverFaceModel(long driverId, String photo) {
        //查询员工的姓名和性别
        HashMap map = driverDao.searchDriverNameAndSex(driverId);
        String name = MapUtil.getStr(map, "name");
        String sex = MapUtil.getStr(map, "sex");

        //腾讯云端创建司机面部档案
        Credential cred = new Credential(secretId, secretKey);
        IaiClient client = new IaiClient(cred, region);
        try {
            CreatePersonRequest req = new CreatePersonRequest();
            //人员库ID
            req.setGroupId(groupName);
            //人员ID
            req.setPersonId(driverId + "");
            long gender = "男".equals(sex) ? 1L : 2L;
            req.setGender(gender);
            //照片质量等级
            req.setQualityControl(4L);
            //重复人员识别等级
            req.setUniquePersonControl(4L);
            //姓名
            req.setPersonName(name);
            //base64图片
            req.setImage(photo);
            CreatePersonResponse resp = client.CreatePerson(req);
            if (StrUtil.isNotBlank(resp.getFaceId())) {
                //更新司机表的archive字段值
                int rows = driverDao.updateDriverArchive(driverId);
                if (rows != 1) {
                    return "更新司机归档字段失败";
                }
            }
        } catch (TencentCloudSDKException e) {
            log.error("创建腾讯云端司机档案失败", e);
            return "创建腾讯云端司机档案失败";
        }
        return "";
    }

    @Override
    public Result vertificateDriverFace(long driverId, String photo) {
        Credential cred = new Credential(secretId, secretKey);
        IaiClient client = new IaiClient(cred, region);
        VerifyPersonRequest req = new VerifyPersonRequest();
        req.setPersonId(driverId+"");
        req.setImage(photo);
        Boolean isMatch = false;
        Result res = Result.ok();
        try {
            VerifyPersonResponse verifyPersonResponse = client.VerifyPerson(req);
            isMatch = verifyPersonResponse.getIsMatch();
            if(isMatch) {
                recognitionDao.insert(driverId);
            }
        } catch (TencentCloudSDKException e) {
            res.put("message", e.getMessage());
            log.error("腾讯云验证人员调用失败", e);
        }
        res.put("result", isMatch);
        return res;
    }

    @Override
    public HashMap login(String code) {
        String openId = microAppUtil.getOpenId(code);
        HashMap result = driverDao.login(openId);
        if(result != null && result.containsKey("archive")) {
            int archive = MapUtil.getInt(result, "archive");
            result.replace("archive", archive==1 ? true : false);
        }
        return result;
    }

    @Override
    public HashMap searchDriverBaseInfo(long driverId) {
        HashMap result = driverDao.searchDriverBaseInfo(driverId);
        Integer realAuth = driverDao.searchDriverIsRealAuth(driverId);
        result.put("realAuth",realAuth);
        JSONObject summary = JSON.parseObject(MapUtil.getStr(result, "summary"));
        result.replace("summary", summary);
        return result;
    }

    @Override
    public PageInfo<HashMap> searchDriverByPage(SearchDriverByPageForm form) {
        Map param = BeanUtil.beanToMap(form);
        PageHelper.startPage(form.getPage(),form.getLength());
        List<HashMap> list = driverDao.searchAllDriver(param);
        PageInfo<HashMap> pageInfo = new PageInfo<>(list);
        return pageInfo;
    }

    @Override
    public HashMap searchDriverAuth(long driverId) {
        HashMap result = driverDao.searchDriverAuth(driverId);
        return result;
    }

    @Override
    public HashMap searchDriverRealSummary(long driverId) {
        HashMap result = driverDao.searchDriverRealSummary(driverId);
        return result;
    }

    @Override
    public HashMap searchDriverIsRealAuth(long driverId) {
        Integer auth = driverDao.searchDriverIsRealAuth(driverId);
        HashMap map = new HashMap();
        map.put("realAuth", auth.equals(1)?"未认证":auth.equals(2)?"已认证":"审核中");
        map.put("realAuthCode", auth);
        return map;
    }

    @Override
    @Transactional
    @LcnTransaction
    public int updateDriverRealAuth(Map param) {
        int rows = driverDao.updateDriverRealAuth(param);
        return rows;
    }

    @Override
    public HashMap searchDriverBriefInfo(long driverId) {
        HashMap map = driverDao.searchDriverBriefInfo(driverId);
        return map;
    }

    @Override
    public HashMap searchCanStartWork(Map param) {
        HashMap map = new HashMap();
        //检查司机是否被禁止接单
        List<DriverLockdownEntity> lockdownList = driverLockdownDao.list(param);
        map.put("lockdown", !lockdownList.isEmpty());
        //TODO 检查司机是否有未缴纳的罚款
        param.put("status", 1);
        List<DriverFineEntity> driverFineList = driverFineDao.selectDriverFine(param);
        map.put("hasFine", !driverFineList.isEmpty());
        //检查是否当天是否存在人脸识别记录
        String count = recognitionDao.hasDriverRecognitionInDay(param);
        if (Integer.parseInt(count) > 0) {
            map.put("faceRecognition", true);
        } else {
            map.put("faceRecognition", false);
        }
        return map;
    }

    @Override
    public Integer updateDriverPhone(UpdatePhoneForm form) {
        List<Long> ids = driverDao.countDriverByPhone(form.getPhone());
        if(ids.size() == 0) {
            Integer rows = driverDao.updateDriverPhone(form);
            return rows;
        }
        for (Long id : ids) {
            if(id.equals(form.getDriverId())) {
                return -2;
            }
        }
        return -1;
    }

    @Override
    public int updateDriverHome(UpdateDriverHomeForm form) {
        //home, driverId
        int rows = driverDao.updateDriverHome(form);
        return rows;
    }
}